using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace Slaks.Analysis.Mediators
{
	public enum AddFileMode
	{
		File,
		Directory
	} ;

	public class FileListMediator
	{
		private ListView m_control;
		private Form m_parent;
		private OpenFileDialog m_addFileFD;

		public FileListMediator(Form parent, ListView control)
		{
			m_parent = parent;
			m_control = control;
			m_addFileFD = new OpenFileDialog();
			m_addFileFD.Multiselect = true;
			m_addFileFD.RestoreDirectory = true;
			m_addFileFD.Title = "Add files to the file list";
			m_addFileFD.Filter = "Xml Document|*.xml|All files|*.*";
		}

		public void AddFiles(AddFileMode mode)
		{
			if (mode == AddFileMode.File)
			{
				AddFiles();
			}
			else
			{
				string directory = AddDirectory();
				RetrieveFilesFromDirectory(directory);
			}
		}

		private string AddDirectory()
		{
			string directory = null;

			try
			{
				FolderBrowserDialog dialog = new FolderBrowserDialog();
				DialogResult result = dialog.ShowDialog();
				if (result == DialogResult.OK)
				{
					string directoryPath = dialog.SelectedPath;
					char lastChar = directoryPath[directoryPath.Length - 1];
					if (!(lastChar.Equals('\\') && lastChar.Equals('/'))) directoryPath += '\\';
					directory = directoryPath;
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(m_parent, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			return directory;
		}

		private void RetrieveFilesFromDirectory(string directory)
		{
			if (directory == null) return;
			string[] files = null;
			files = Directory.GetFiles(directory, "*.xml");
			if (files != null) AddNewFilesToList(files);
		}

		private delegate void AddNewFilesToListHandler(string[] files);

		/// <summary>
		/// Check for duplicate files and add only unique
		/// </summary>
		/// <param name="files"></param>
		private void AddNewFilesToList(string[] files)
		{
			if (m_control.InvokeRequired)
			{
				m_control.BeginInvoke(new AddNewFilesToListHandler(AddNewFilesToList), new object[] {files});
				return;
			}
			m_control.BeginUpdate();
			for (int i = 0; i < files.Length; i++)
			{
				m_control.Items.Add(files[i]);
			}
			m_control.EndUpdate();
		}

		/// <summary>
		/// Add files to the list of files to parse
		/// </summary>
		/// <returns></returns>
		private void AddFiles()
		{
			string[] files = null;
			try
			{
				if (m_addFileFD.ShowDialog() == DialogResult.OK)
				{
					files = m_addFileFD.FileNames;
					AddNewFilesToList(files);
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(m_parent, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
		}

		private delegate void ClearFileListHandler();

		public void ClearFileList()
		{
			if (m_control.InvokeRequired)
			{
				m_control.BeginInvoke(new ClearFileListHandler(ClearFileList), null);
				return;
			}
			m_control.BeginUpdate();
			m_control.Items.Clear();
			m_control.EndUpdate();
		}


		private delegate void DeleteFilesHandler();

		public void DeleteFiles()
		{
			ListView.SelectedIndexCollection indices = m_control.SelectedIndices;
			if (indices.Count <= 0) return;

			if (m_control.InvokeRequired)
			{
				m_control.BeginInvoke(new DeleteFilesHandler(DeleteFiles), null);
				return;
			}

			for (int i = indices.Count - 1; i >= 0; i--)
			{
				m_control.Items.RemoveAt(indices[i]);
				indices = m_control.SelectedIndices;
			}
		}

		public void CountFiles()
		{
			MessageBox.Show(m_parent, m_control.Items.Count.ToString() + " files in the list", "File Counter");
		}

		public void SaveFileList()
		{
			if (m_control.Items.Count <= 0) return;

			SaveFileDialog saveDialog = new SaveFileDialog();
			saveDialog.Filter = "Document file list|*.xml|All files|*.*";
			saveDialog.Title = "Save file list";

			if (saveDialog.ShowDialog() == DialogResult.OK)
			{
				FileStream fs = null;
				try
				{
					string fileName = saveDialog.FileName;

					XmlSerializer xs = new XmlSerializer(typeof (string[]));
					fs = File.OpenWrite(fileName);

					string[] files = new string[m_control.Items.Count];

					int i = 0;
					foreach (ListViewItem item in m_control.Items)
					{
						files[i++] = item.Text;
					}

					xs.Serialize(fs, files);

					MessageBox.Show(m_parent, "File list successfully saved", "Save", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				}
				catch (Exception ex)
				{
					MessageBox.Show(m_parent, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
				}
				finally
				{
					if (fs != null) fs.Close();
				}

			}
		}

		public void LoadFileList()
		{
			OpenFileDialog loadDialog = new OpenFileDialog();
			loadDialog.Filter = "Document file list|*.xml|All files|*.*";
			loadDialog.Title = "Load file list";

			FileStream fs = null;
			if (loadDialog.ShowDialog() == DialogResult.OK)
			{
				try
				{
					string fileName = loadDialog.FileName;

					XmlSerializer xs = new XmlSerializer(typeof (string[]));
					fs = File.OpenRead(fileName);
					string[] files = (string[]) xs.Deserialize(fs);

					if (files == null) return;

					this.AddNewFilesToList(files);

					MessageBox.Show(m_parent, "File list successfully loaded", "Load", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				}
				catch (Exception ex)
				{
					MessageBox.Show(m_parent, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
				}
				finally
				{
					if (fs != null) fs.Close();
				}

			}
		}


		public void ShowSelectedFiles()
		{
			string[] files = GetSelectedFiles();
			if (files == null) return;

			for (int i = 0; i < files.Length; i++)
			{
				Process.Start(files[i]);
			}
		}

		public string[] GetSelectedFiles()
		{
			ListView.SelectedIndexCollection indices = m_control.SelectedIndices;
			if (indices.Count <= 0) return null;

			string[] files = new string[indices.Count];

			for (int i = 0; i < indices.Count; i++)
			{
				files[i] = m_control.Items[indices[i]].Text;
			}
			return files;
		}

	}
}